import { nanoid } from 'nanoid';
import { Client } from 'paho-mqtt';
import { Subject } from 'rxjs';
import { excludeKeys, getKey, pool } from './pool';
// 初始化mqtt
const client = new Client('wss://mqtt.anlan.tech:8084/mqtt', nanoid());
const subject = new Subject();
//连接丢失回调
client.onConnectionLost = (error : Paho.MQTT.MQTTError) => {
  console.error(error);
};
// 消息投递
client.onMessageDelivered = (message : Paho.MQTT.Message) => {
  const topic = message.destinationName;
  const key = getKey(topic);
  if (pool[key]) {
    toNextState(key);
  }
};
// 监听数据
client.onMessageArrived = (message : Paho.MQTT.Message) => {
  const topic = message.destinationName;
  const payloadString = message.payloadString;
  onMsg(topic, payloadString);
};
// 客户端连接到其服务器
const connectionOptions : Paho.MQTT.ConnectionOptions = {
  useSSL: true,
  userName: 'ZLrSE2Az4wuCmjpI',
  password: 'BZUS801mDRw4iqI7',
  reconnect: true,
  onSuccess() {
    console.log('MQTT connected');
  },
  onFailure(err) {
    console.error(err);
  },
};
client.connect(connectionOptions);
/**
 * 接收返回的数据信息
 * @param topic 主题
 * @param msg   返回消息
 */
function onMsg(topic : string, msg : string) {
  const key = getKey(topic);
  if (excludeKeys.includes(key)) {
    subject.next(JSON.parse(msg));
  } else if (pool[key]) {
    pool[key].onMsg(JSON.parse(msg));
    toNextState(key);
  }
}

function toNextState(key : string) {
  pool[key].machineService.send({ type: 'NEXT' });
}
//发送
function publish(topic : string, data : any, qos : Paho.MQTT.Qos = 2) {
  const msg = JSON.stringify(data);
  client.send(topic, msg, qos);
}
//订阅
function subscribe(topic : string, subcribeOptions : Paho.MQTT.SubscribeOptions = { qos: 2 }) {
  subcribeOptions.onSuccess = () => {
    const key = getKey(topic);
    if (pool[key]) {
      toNextState(key);
    }
  };
  client.subscribe(topic, subcribeOptions);
}
//取消订阅
function unsubscribe(topic : string, unsubcribeOptions : Paho.MQTT.UnsubscribeOptions = {}) {
  client.unsubscribe(topic, unsubcribeOptions);
}

export { publish, subscribe, unsubscribe, client, subject };